#include <iostream>
#include "pthread.hpp"
#include "blockqueue.hpp"
#include "task.hpp"
#include <ctime>
using namespace mypthread;
//  基于阻塞队列的生产者、消费者模型，阻塞队列就是交易场所（共享资源）

// using BlockQueue_t = BlockQueue<int>; //定义一个宏，等价于#define BlockQueue_t BlockQueue<int>
using BlockQueue_t = BlockQueue<Task>; //这里有分号
// 这样写的目的是：不需要大面积修改代码，因为阻塞队列的元素不一定是int、Task等类型，一旦更换类型，就要调整下面的所有代码，

// 生产者方法
void producer(BlockQueue_t &bq)
{
    srand((unsigned int)time(nullptr) ^ pthread_self());
    while (true)
    {
        sleep(1);
        int a = rand() % 100;
        int b = rand() % 100;
        Task t(a, b);
        bq.push(t);
        cout << "producer assign task is: " << t.debugToString() << endl; // 打印布置的任务信息
    }
}

// 消费者方法
void consumer(BlockQueue_t &bq)
{
    // sleep(5);
    while (true)
    {
        sleep(1);
        // 1、获取任务
        Task t;
        bq.pop(t);

        // 2、处理任务
        t.excute();
        cout << "consumer handle task is: " << t.resultToString() << endl;
    }
}

// 创建线程
void createComThread(vector<Thread<BlockQueue_t>> &threads, int num, BlockQueue_t &bq, func_t<BlockQueue_t> func)
{
    for (int i = 0; i < num; i++)
    {
        string name = "thread-" + to_string(i + 1);
        threads.emplace_back(func, bq, name);
        sleep(1);
    }
}

// 创建生产者
void createProducer(vector<Thread<BlockQueue_t>> &threads, int num, BlockQueue_t &bq)
{
    createComThread(threads, num, bq, producer);
}

// 创建消费者
void createConsumer(vector<Thread<BlockQueue_t>> &threads, int num, BlockQueue_t &bq)
{
    createComThread(threads, num, bq, consumer);
}

// 等待所有线程
void waitPthread(vector<Thread<BlockQueue_t>> &threads)
{
    for (auto e : threads)
        e.join();
}

int main()
{

    // 生产者、消费者交易的数据是int类型
    // BlockQueue<int> bq(5); // 定义一个阻塞队列，队列可以放5个元素
    // vector<Thread<BlockQueue<int>>> threads;

    // 生产者、消费者交易的数据是自定义Task
    BlockQueue<Task> bq(5); // 定义一个阻塞队列，队列可以放5个元素
    vector<Thread<BlockQueue_t>> threads;

    // 创建生产者
    createProducer(threads, 3, bq);

    // 创建消费者
    createConsumer(threads, 5, bq);

    // 等待所有线程
    waitPthread(threads);

    return 0;
}
